from django_redis import get_redis_connection
from rest_framework import serializers

from users.models import User
from .utils import check_save_user_token
from .models import OAuthUser


class QQAuthUserSerializer(serializers.Serializer):
    """
    　　新用户的登陆并且绑定ＱＱ号码，涉及到两个数据库的数据新建记录
    　　所以需要重新定义函数create，保证数据保存至数据库中，　在视图中
    　　不能定义model=xxxx,需要自己全部重新定义，将数据序列化和反序列化
    　　　前段传如入的数据为
        mobile	　　　　str	是	手机号
        password	　　str	是	密码
        sms_code	　　str	是	短信验证码
        access_token	str	是	凭据 （包含openid)

        返回值为：
        token	　　　str	是	JWT token(调用相应的模块)
        id	　　　　　int	　　是	用户id
        username	str	　　是	用户名
    """
    mobile = serializers.RegexField(label="手机号码", regex=r"^1[3-9]\d{9}$")
    password = serializers.CharField(label="密码", min_length=8, max_length=20)
    sms_code = serializers.CharField(label="短信验证码")
    access_token = serializers.CharField(label="验证凭证", write_only=True)

    def validate_access_token(self, value):
        """验证access_token"""
        # print(value)
        openid = check_save_user_token(value)
        # print(openid)
        if openid is None:
            raise serializers.ValidationError({"message": "无效的access_token"})
        return openid

    def validate(self, attrs):
        """验证所有的数据，注意需要返回值"""
        # 1 验证加密和限时的access_token的值, 解密后验证(单独验证)
        # access_token = attrs.get("access_token")
        # openid = check_save_user_token(access_token)
        # if not openid:
        #     raise serializers.ValidationError("无效的access_token")
        # attrs["openid"] = openid

        # 2 验证短信验证码
        # 连接数据库　　获取mobile　　查找相应的值　　比较
        mobile = attrs.get("mobile")
        sms_code = attrs.get("sms_code")
        redis_conn = get_redis_connection("verify")
        try:
            real_sms_code = redis_conn.get("sms_%s" % mobile)
            real_sms_code = real_sms_code.decode()
        except Exception as e:
            raise serializers.ValidationError({"message": "无效的短信验证码"})

        if real_sms_code != sms_code:
            raise serializers.ValidationError("短信验证码错误")

        # 2　用户和密码的校验
        # 可能用户已经存在　　或者是新的用户
        try:
            user = User.objects.get(mobile=mobile)
            attrs["user"] = user
        except User.DoesNotExist:  # 用户不存在，继续执行下面的代码，不鞥抛出异常
            pass
        else:
            password = attrs.get("password")
            if not user.check_password(password):
                raise serializers.ValidationError("用户的密码错误")
        return attrs

    def create(self, validated_data):
        """ 保存数据至两个数据库"""
        # 首先查询是不是已经存在相应的用户（用户不存在attrs的键为mobile passowrd sms_code）
        # 如果用户存在，　则attrs的键含有user
        user = validated_data.get("user")

        # 向视图对象中补充user对象属性，以便在视图中使用use(后续增加的)
        self.context['view'].user = user

        # 如果用户不存在，则新增用户，保存值数据库,用户名暂未手机号码
        if user is None:
            user = User.objects.create(
                username=validated_data["mobile"],
                password=validated_data["password"],
                mobile=validated_data["mobile"]

            )
            # 密码需要加密保存
            user.set_password(validated_data["password"])
            user.save()
        # 保存用户和openid至数据库中

        OAuthUser.objects.create(
            openid=validated_data["access_token"],
            user=user
        )
        return user
        # return user 返回用户的信息，用于视图
